package cn.seaboot.flake.call;

import cn.seaboot.flake.mapping.ParameterMap;
import cn.seaboot.flake.mapping.ParameterMapping;
import org.apache.ibatis.mapping.ParameterMode;
import org.jetbrains.annotations.NotNull;
import org.springframework.jdbc.core.CallableStatementCreator;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

/**
 * 基于 {@link ParameterMap} 设计的 CallableStatementCreator，用于调用存储过程
 *
 * @author Mr.css
 * @version 2022-01-28 11:04
 */
public class FlackCallableStatementCreator implements CallableStatementCreator {

    /**
     * 参数配置
     */
    private final ParameterMap parameterMap;
    /**
     * 实际传参
     */
    private final Map<String, Object> params;
    /**
     * 查询语句
     */
    private final String sql;

    public FlackCallableStatementCreator(String sql, ParameterMap parameterMap, Map<String, Object> params) {
        this.sql = sql;
        this.parameterMap = parameterMap;
        this.params = params;
    }

    @NotNull
    @Override
    public CallableStatement createCallableStatement(Connection con) throws SQLException {
        List<ParameterMapping> parameterMappings = parameterMap.getParameterMappings();
        CallableStatement cs = con.prepareCall(sql);
        int idx = 1;
        for (ParameterMapping mapping : parameterMappings) {
            if (mapping.getMode() == ParameterMode.IN) {
                cs.setObject(idx, params.get(mapping.getProperty()));
            } else if (mapping.getMode() == ParameterMode.OUT) {
                cs.registerOutParameter(idx, mapping.getJdbcType().TYPE_CODE);
            } else {
                cs.setObject(idx, params.get(mapping.getProperty()));
                cs.registerOutParameter(idx, mapping.getJdbcType().TYPE_CODE);
            }
            idx++;
        }
        return cs;
    }
}
